package top.songxs.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.util.CollectionUtils;
import top.songxs.base.BaseDao;
import top.songxs.base.BaseServiceImpl;
import top.songxs.dao.PermissionDao;
import top.songxs.dao.RolePermissionDao;
import top.songxs.entity.Permission;
import top.songxs.entity.RolePermission;
import top.songxs.helper.PermissionHelper;
import top.songxs.service.PermissionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service(interfaceClass = PermissionService.class)
@Transactional
public class PermissionServiceImpl extends BaseServiceImpl<Permission> implements PermissionService {
    @Autowired
    private PermissionDao permissionDao;

    @Override
    protected BaseDao<Permission> getEntityDao() {
        return permissionDao;
    }

    @Override
    public List<Map<String, Object>> findPermissionsByRoleId(Long roleId) {
        //获取所有的权限列表
        List<Permission> permissionList = this.permissionDao.findAll();
        //获取当前角色的权限id列表
        List<Long> permissionIdList = this.permissionDao.findPermissionByRoleId(roleId);
        //根据当前角色的权限id列表准备zTree数据
        //{ id:2, pId:0, name:"随意勾选 2", checked:true, open:true}
        List<Map<String, Object>> zNodes = new ArrayList();
        for (Permission permission : permissionList) {
            Map<String, Object> zNode = new HashMap();
            zNode.put("id", permission.getId());
            zNode.put("pId", permission.getParentId());
            zNode.put("name", permission.getName());
            zNode.put("checked", permissionIdList.contains(permission.getId()));
            //zNode.put("open",); //open不在后台赋值，在前台处理
            zNodes.add(zNode);

        }
        //返回结果
        return zNodes;
    }

    @Autowired
    private RolePermissionDao rolePermissionDao;

    @Override
    public void saveRolePermissionRealtionShip(Long roleId, Long[] permissionIds) {
        //删除之前的权限列表
        rolePermissionDao.deleteByRoleId(roleId);

        //添加现在新的权限列表
        if (!StringUtils.isEmpty(permissionIds)) {
            for (Long permissionId : permissionIds) {
                RolePermission rolePermission = new RolePermission();
                rolePermission.setRoleId(roleId);
                rolePermission.setPermissionId(permissionId);
                this.rolePermissionDao.insert(rolePermission);
            }
        }
    }

    @Override
    public List<Permission> findMenuPermissionByAdminId(Long adminId) {
        //获取用户的权限列表（不带下级）
        List<Permission> permissionList = null; //
        if (adminId == 1) {
            permissionList = this.permissionDao.findAllMenuPermission();
        } else {
            permissionList = this.permissionDao.findMenuPermissionByAdminId(adminId);
        }
        //将用户的权限列表转换为动态菜单的形式（带下级）
        List<Permission> result = null;//
        result = PermissionHelper.bulid(permissionList);
        return result;
    }

    @Override
    public List<String> findCodeListByAdminId(Long adminId) {
        //获取用户的权限列表（不带下级）
        List<String> codeList = null; //
        if (adminId == 1) {
            codeList = this.permissionDao.findAllCodeList();
        } else {
            codeList = this.permissionDao.findCodeListByAdminId(adminId);
        }
        return codeList;
    }

    @Override
    public List<Permission> findAllMenu() {
        //调用持久层的方法 查询所有菜单
        List<Permission> permissionLists = permissionDao.findAll();
        //使用PermissionHelper构建父子级菜单
        return PermissionHelper.bulid(permissionLists);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void delete(Serializable id) {
        //重写delete方法
        //要判断当前要删除的这个菜单是否有子菜单，如果有则不能删除
        //1.根据当前菜单的id在acl_permission表中查询子菜单的数量,如果数量大于零
        List<Permission> permissionList = permissionDao.findPermissionListByParentId(id);
        if (!CollectionUtils.isEmpty(permissionList)) {
            throw new RuntimeException("当前要删除的菜单有子菜单，不能够删除！ ");
        }
        //如果查询到的子菜单列表为空，则可以删除
        //2根据id删除菜单
        super.delete(id);
        //如果菜单删了 那么与菜单关联的角色也应该删除
        //根据菜单id删除角色与菜单（权限）的一个关联信息
        rolePermissionDao.removeByPremissionId(id);
    }

    //重写基本方法并添加严谨性判断
    @Override
    public int insert(Permission permission) {
        //判断当前要新增的的菜单的父菜单中是否有同名子菜单了，如果有则不能新增
        Long parentId = permission.getParentId();
        //根据父菜单id查询所有父菜单的所有子菜单
        List<Permission> permissionList = permissionDao.findPermissionListByParentId(parentId);
        if (!CollectionUtils.isEmpty(permissionList)) {//判断得到的集合是否是空 不为空则遍历每一个元素
            for (Permission child : permissionList) {
                if (child.getName().equals(permission.getName())) {
                    //判断父菜单的子菜单列表是否有跟当前新增的菜单同名的菜单
                    //如果有则不能新增成功
                    throw new RuntimeException("当前父菜单中存在同名子菜单不能新增");
                }
            }
        }
        return super.insert(permission);
    }

    //重写基本方法并添加 严谨性判断 随添加菜单时同名菜单不能添加，
    // 但是架不住先添加再修改所以在这里添加健壮性判断
    @Override
    public int update(Permission permission) {
        //判断当前要修改的菜单的父菜单中是否有同名子菜单

        Long parentId = permission.getParentId();
        //根据父菜单id查询所有父菜单的所有子菜单
        List<Permission> permissionList = permissionDao.findPermissionListByParentId(parentId);
        if (!CollectionUtils.isEmpty(permissionList)) {//判断得到的集合是否是空 不为空则遍历每一个元素
            for (Permission child : permissionList) {

                //这里要加一条，跟上面还有点不一样
                //判断是否有同名子菜单，并且这个同名子菜单不能是当前要修改的这条数据
                /**
                 * 这里解释下，因为修改的话如果只修改其他不修改名字，这样前端传过来的permission的name也存在
                 * 在数据库中，这样逻辑上是可以的，但是不判断id的话就会修改失败 ，所以加一句判断id
                 */
                if (child.getName().equals(permission.getName()) && !child.getId().equals(permission.getId())) {
                    //判断父菜单的子菜单列表是否有跟当前新增的菜单同名的菜单
                    //如果有则不能新增成功
                    throw new RuntimeException("当前父菜单中存在同名子菜单不能新增");
                }
            }
        }

        return super.update(permission);
    }
}
